package com.code.learn.Ipersistance.sqlSession;

import com.code.learn.Ipersistance.config.Configuration;
import com.code.learn.Ipersistance.config.MappedStatement;
import com.code.learn.Ipersistance.io.Resources;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.PropertyVetoException;
import java.io.*;
import java.util.List;
import java.util.Properties;

/**
 * @author Nina
 * @create 2020/12/7 下午5:08
 * @desc 作为xml读取配置类使用
 */
public class XMLConfigBuilder {

    // 本类主要是封装Configuration，所以这里构建无参实例的时候直接返回Configuration
    private Configuration configuration;

    public XMLConfigBuilder(){
        this.configuration = new Configuration();
    }
    /**
     * 基于dom4j解析xml配置文件，包装到Configuration中
     * @param inputStream
     * @return
     * @throws DocumentException
     * @throws PropertyVetoException
     */
    public Configuration buildConfig(InputStream inputStream) throws DocumentException, PropertyVetoException {
        Document document = new SAXReader().read(inputStream);
        // sqlMapConfig.xml中的rootElement == configuration
        Element rootElement = document.getRootElement();
        // 方法是selectNodes，不是elements,使用xpath形式获取到所有的property的element
        List<Element> elementList = rootElement.selectNodes("//property");
        // 使用Properties来接收下key-value
        Properties properties = new Properties();
        for (Element element : elementList) {
            properties.setProperty(element.attributeValue("name"), element.attributeValue("value"));
        }
        // 封装数据源
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
        comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
        comboPooledDataSource.setUser(properties.getProperty("username"));
        comboPooledDataSource.setPassword(properties.getProperty("password"));
        configuration.setDataSource(comboPooledDataSource);

        // 解析所有在sqlMapConfig.xml中配置的业务sql映射文件
        List<Element> mapperList = rootElement.selectNodes("//resource");

        // 遍历处理所有的mapper.xml
        for (Element mapper : mapperList) {
            // 相当于dom4j解析mapper.xml读取到内存中的字节流
            Document mapperDocument = new SAXReader().read(Resources.getResourceAsStream(mapper.attributeValue("name")));
            Element element = mapperDocument.getRootElement();
            // 这里目前只有select方法
            List<Element> selects = element.selectNodes("//select");
            // 解读select方法的id，参数类型，返回类型以及sql语句，全部封装到Configuration的mappedStatementMap中，key=namespace.id
            for (Element select : selects) {
                MappedStatement mappedStatement = new MappedStatement();
                String id = select.attributeValue("id");
                mappedStatement.setId(id);
                mappedStatement.setParameterType(select.attributeValue("parameterType"));
                mappedStatement.setResultType(select.attributeValue("resultType"));
                // 注意：获取sql的时候为空
//                mappedStatement.setSql(select.attributeValue("value"));
                mappedStatement.setSql(select.getTextTrim());
                configuration.getMappedStateMentMap().put(element.attributeValue("namespace")+"."+id,mappedStatement);
            }

            List<Element> inserts = element.selectNodes("//insert");
            // 解读select方法的id，参数类型，返回类型以及sql语句，全部封装到Configuration的mappedStatementMap中，key=namespace.id
            for (Element select : inserts) {
                MappedStatement mappedStatement = new MappedStatement();
                String id = select.attributeValue("id");
                mappedStatement.setId(id);
                mappedStatement.setParameterType(select.attributeValue("parameterType"));
                mappedStatement.setResultType(select.attributeValue("resultType"));
                // 注意：获取sql的时候为空
//                mappedStatement.setSql(select.attributeValue("value"));
                mappedStatement.setSql(select.getTextTrim());
                configuration.getMappedStateMentMap().put(element.attributeValue("namespace")+"."+id,mappedStatement);
            }

            List<Element> updates = element.selectNodes("//update");
            // 解读select方法的id，参数类型，返回类型以及sql语句，全部封装到Configuration的mappedStatementMap中，key=namespace.id
            for (Element select : updates) {
                MappedStatement mappedStatement = new MappedStatement();
                String id = select.attributeValue("id");
                mappedStatement.setId(id);
                mappedStatement.setParameterType(select.attributeValue("parameterType"));
                mappedStatement.setResultType(select.attributeValue("resultType"));
                // 注意：获取sql的时候为空
//                mappedStatement.setSql(select.attributeValue("value"));
                mappedStatement.setSql(select.getTextTrim());
                configuration.getMappedStateMentMap().put(element.attributeValue("namespace")+"."+id,mappedStatement);
            }

            List<Element> deletes = element.selectNodes("//delete");
            // 解读select方法的id，参数类型，返回类型以及sql语句，全部封装到Configuration的mappedStatementMap中，key=namespace.id
            for (Element select : deletes) {
                MappedStatement mappedStatement = new MappedStatement();
                String id = select.attributeValue("id");
                mappedStatement.setId(id);
                mappedStatement.setParameterType(select.attributeValue("parameterType"));
                mappedStatement.setResultType(select.attributeValue("resultType"));
                // 注意：获取sql的时候为空
//                mappedStatement.setSql(select.attributeValue("value"));
                mappedStatement.setSql(select.getTextTrim());
                configuration.getMappedStateMentMap().put(element.attributeValue("namespace")+"."+id,mappedStatement);
            }
        }
        return configuration;
    }
}
